package org.tgit.gateway.common;


import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.springframework.cache.Cache;
import org.springframework.util.StringUtils;
import org.tgit.gateway.domain.ApiInfo;
import org.tgit.gateway.domain.ApiMonitorInfo;
import org.tgit.gateway.domain.AuthAppApiInfo;
import org.tgit.gateway.domain.NetStatusInfo;


/**
 * 消息队列处理类
 * @author fanzaijun
 * 2017年6月27日
 */
public class MessageQueueUtil {
	//apiLogQuene日志
	private static Queue<String> apiLogConcurrentQuene=new ConcurrentLinkedQueue<String>();
    // 存储当前:对端网络连通的本地缓存
    private static Map<String, NetStatusInfo> netStatusConcurrentMap= new ConcurrentHashMap<String, NetStatusInfo>();
    // 存储当前:系统中记录的已经被网关移除的服务器信息
    private static Queue<String> apiServicesExceptionConcurrentQqene = new ConcurrentLinkedDeque<String>();
    // 存储当前:系统网关中存放的APPAPI的Token信息
    private static Map<String, String> appApiTokenConcurrentMap = new ConcurrentHashMap<String, String>();
    // 存储当前:API的访问URI与API对象的缓存
    private static Map<String,ApiInfo> apiAccessUriConcurrentMap = new ConcurrentHashMap<String,ApiInfo>();
    // API注册的时候由于外部调用存在数据库延时的情况，因此在注册时候没有查询到待注册信息的时候，使用后端定时任务轮训机制进行注册
    private static Map<String,Integer> registerApiFailConcurrentMap = new ConcurrentHashMap<String,Integer>();
    
    /**
     * 
    * @Title: removeRegisterApiFail   
    * @Description: 将某个API从注册缓存中删除
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:29:05   
    * @param apiId  
    * void  
    * @throws (没有异常抛出)
     */
    public static void removeRegisterApiFail(String apiId){
    	registerApiFailConcurrentMap.remove(apiId);
    }
    /**
     * 
    * @Title: modifyRegisterApiFail   
    * @Description: 修改当前存储的注册API的状态信息
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:28:52   
    * @param apiId
    * @param times  
    * void  
    * @throws (没有异常抛出)
     */
    public static void modifyRegisterApiFail(String apiId , Integer times){
    	registerApiFailConcurrentMap.put(apiId, times);
    }
    
    /**
     * 
    * @Title: setApiLogQueneValue   
    * @Description: 网关打印日志的队列
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:28:31   
    * @param value  
    * void  
    * @throws (没有异常抛出)
     */
    public static  void setApiLogQueneValue(String value){
    	apiLogConcurrentQuene.add(value);
    }
    
    /**
     * 
    * @Title: getApiLogQuene   
    * @Description: 获取日志队列
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:30:30   
    * @return  
    * Queue<String>  
    * @throws (没有异常抛出)
     */
    public static Queue<String>  getApiLogQuene(){
    	return apiLogConcurrentQuene;
    }
    /**
     * 获取注册失败的API列表
     * @return
     */
    public static Map<String,Integer> getAllRegisterApiFail(){
    	return registerApiFailConcurrentMap;
    }
    
    /**
     * 将当前注册的API失败信息记录到缓存中
     * @param apiId
     */
    public static void addRegisterApiFail(String[] apiIds){
    	if (!StringUtils.isEmpty(apiIds)){
    		for (String apiId : apiIds) {
    			registerApiFailConcurrentMap.put(apiId, 0);
			}
    	}
    }
    
    /**
     * 
    * @Title: putCacheKeyValue   
    * @Description: 加入到缓存
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:08:34   
    * @param gatewayCache
    * @param cackeKey
    * @param key
    * @param obj  
    * void  
    * @throws (没有异常抛出)
     */
    public static void  putCacheKeyValue(Cache gatewayCache,String cackeKey,String key,Object obj){
    	Map<String,Object> map=new HashMap<String,Object>();
    	map.put(key, obj);
		gatewayCache.put(cackeKey,map);
	}
    
    /**
     * 将访问URI与API对象存储到缓存中
     * @param redisTemplate
     * @param accessUri
     * @param ApiInfo
     * @param nodeId
     */
    public static void putApiInfoByAccessUri(Cache gatewayCache,String accessUri,ApiInfo apiInfo,String nodeId){
        //缓存中存储MD5加密后的key，减少key的长度
        String uriKey = MD5Utils.md5(accessUri);
        String cacheKey = CommonUtil.getCacheKey(ApiConstants.API_ACCESSURI_CACHE_KEY , nodeId);
        putCacheKeyValue(gatewayCache, cacheKey, uriKey,CommonUtil.toJson(apiInfo));
       	apiAccessUriConcurrentMap.put(uriKey, apiInfo);
    }
    
    /**
     * 根据访问URI获取对应的ApiInfo对象
     * @param accessUri
     * @return
     */
    @SuppressWarnings("unchecked")
    public static ApiInfo getApiInfoByAccessUri(Cache gatewayCache,String accessUri,String nodeId){
        //缓存中存储MD5加密后的key，减少key的长度
        String uriKey = MD5Utils.md5(accessUri);
        String cacheKey = CommonUtil.getCacheKey(ApiConstants.API_ACCESSURI_CACHE_KEY , nodeId);
		Object cacheObj=null==(Map<String,Object>)gatewayCache.get(cacheKey).get()?null:((Map<String,Object>)gatewayCache.get(cacheKey).get()).get(uriKey);
        if (cacheObj != null){
        	return CommonUtil.fromJson(cacheObj.toString(), ApiInfo.class);
        }
        return apiAccessUriConcurrentMap.get(uriKey);
    }
    
    /**
     * 获取存储到缓存中的正式Token
    * @Title: getRealAccessToken   
    * @Description: TODO(这里用一句话描述这个方法的作用)
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:24:02   
    * @param gatewayCache
    * @param apiMonitorInfo
    * @param nodeId
    * @return  
    * String  
    * @throws (没有异常抛出)
     */
    @SuppressWarnings("unchecked")
    public static String getRealAccessToken(Cache gatewayCache,ApiMonitorInfo apiMonitorInfo,String nodeId){
        if (apiMonitorInfo == null){
            return "";
        }
        //appCode_apiId
        String appapi = apiMonitorInfo.getAppCode()+ApiConstants.SYMBOL+apiMonitorInfo.getApiId();
        
        String cacheKey = CommonUtil.getCacheKey(ApiConstants.APP_API_TOKEN_KEY , nodeId);
		Object token =((Map<String,Object>)gatewayCache.get(cacheKey).get()).get(appapi);
		if (token != null){
            return token.toString();
        }
        return appApiTokenConcurrentMap.get(appapi);
    }
	
    /**
     * 
    * @Title: putCacheMap   
    * @Description: 这里用一句话描述这个方法的作用
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:31:26   
    * @param gatewayCache 缓存对象
    * @param cackeKey key值
    * @param key map的key
    * @param value  map的value
    * void  
    * @throws (没有异常抛出)
     */
	public static  void  putCacheMap(Cache gatewayCache,String cackeKey,String key,String value){
		Map<String,Object> map=new HashMap<String,Object>();
		map.put(key, value);
		gatewayCache.put(cackeKey,map);
	}
	
	
	/**
	 * 
	* @Title: saveAppApiTokenInfo   
	* @Description: 保存app-api-token信息到缓存
	* @author fanzaijun  
	* @date 2018年10月25日 下午2:32:28   
	* @param cache
	* @param authAppApiInfo
	* @param nodeId  
	* void  
	* @throws (没有异常抛出)
	 */
    public static void saveAppApiTokenInfo(Cache cache , AuthAppApiInfo authAppApiInfo,String nodeId){
    	//appcode_api
        String appapi = authAppApiInfo.getAppCode()+ApiConstants.SYMBOL+authAppApiInfo.getApiId();
        //app_api_token_serviceid
        String cacheKey = CommonUtil.getCacheKey(ApiConstants.APP_API_TOKEN_KEY , nodeId);
        //cache:app_api_token_serviceid:Map<appcode_api,accessToeken>
        putCacheMap(cache, cacheKey, appapi,authAppApiInfo.getAccessToken());
        //variable:appcode_api:accessToeken
        appApiTokenConcurrentMap.put(appapi, authAppApiInfo.getAccessToken());
        return ;
    }
    
    /**
     * 
    * @Title: removeAllApiServer   
    * @Description: 清除api-server队列
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:26:47     
    * void  
    * @throws (没有异常抛出)
     */
    public static void removeAllApiServer(){
        apiServicesExceptionConcurrentQqene.clear();
    }
    
    /**
     * 
    * @Title: deleteApiServer   
    * @Description: 将API部署服务器从缓存列表中删除
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:37:48   
    * @param serverId  
    * void  
    * @throws (没有异常抛出)
     */
    public static void deleteApiServer(String serverId){
        apiServicesExceptionConcurrentQqene.remove(serverId);
    }
    
    /**
     * 
    * @Title: existApiServer   
    * @Description: 判断当前传入的API部署服务器原来是否已经被从网关中删除
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:37:25   
    * @param serverId
    * @return  
    * boolean  
    * @throws (没有异常抛出)
     */
    public static boolean existApiServer(String serverId){
        return apiServicesExceptionConcurrentQqene.contains(serverId);
    }
 
    /**
     * 
    * @Title: addRemovedApiServer   
    * @Description: 将已经失效的API部署服务器记录到缓存列表中
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:37:08   
    * @param serverId  
    * void  
    * @throws (没有异常抛出)
     */
    public static void addRemovedApiServer(String serverId){
        apiServicesExceptionConcurrentQqene.add(serverId);
    }
    
    /**
     * 
    * @Title: getNetBean   
    * @Description: 根据传入的Key获取当前的网络状态
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:36:41   
    * @param key
    * @return  
    * NetStatusInfo  
    * @throws (没有异常抛出)
     */
    public static NetStatusInfo getNetBean(String key){
        if (CommonUtil.isEmpty(key)){
            return null;
        }
        return netStatusConcurrentMap.get(key);
    }
    
    /**
     * 
    * @Title: putNetStatus   
    * @Description: 将当前网络状态回写到缓存中
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:36:26   
    * @param key
    * @param bean  
    * void  
    * @throws (没有异常抛出)
     */
    public static void putNetStatus(String key , NetStatusInfo bean){
        netStatusConcurrentMap.put(key, bean);
    }
    
    /**
     * 
    * @Title: getAllNetStatus   
    * @Description: 获取当前缓存中存放的所有网络连通的缓存，key为接收方地址
    * @author fanzaijun  
    * @date 2018年10月25日 下午2:36:13   
    * @return  
    * Map<String,NetStatusInfo>  
    * @throws (没有异常抛出)
     */
    public static Map<String , NetStatusInfo> getAllNetStatus(){
        return netStatusConcurrentMap;
    }
    
}
